package services

import (
	"errors"
	"fmt"
	beego "github.com/beego/beego/v2/adapter"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
	"weiboxs.com/new_h_glasses/models"
	"weiboxs.com/new_h_glasses/utils"
)

//接口地址
const getSmsApiURL = "http://web.cr6868.com/asmx/smsservice.aspx?%s"

type SmsService struct {
	User      string
	Pwd       string
	Signature string
}

//短信发送参数
type SmsArgv struct {
	Typeid       int      //短信类型【1验证短信,2普通短信】
	DepartmentId int64    //部门ID
	CreatedBy    string   //创建人
	Mobile       string   //单条发送
	Mobiles      []string //批量发送
	SendTiime    string   //定时发送
	Content      string   //短信内容
	VerifCode    string   //验证码
}

//初始化短信
func NewSms() (*SmsService, error) {
	sms := &SmsService{}
	sms.User = beego.AppConfig.String("sms::sms_user")
	sms.Pwd = beego.AppConfig.String("sms::sms_pwd")
	sms.Signature = beego.AppConfig.String("sms::sms_signature")
	if len(sms.User) <= 0 || len(sms.Pwd) <= 0 || len(sms.Signature) <= 0 {
		utils.LogWarning(errors.New("短信配置错误")) //记录错误情况
		return sms, errors.New("短信配置错误")
	}
	return sms, nil
}

/*
*发送短信
*mobile 手机号
*content 短信内容
*sendtime 发送时间
*/
func (s *SmsService) Send(argv *SmsArgv) error {
	if !utils.CheckMobile(argv.Mobile) {
		return errors.New("手机号不正确")
	}
	if len(argv.Content) <= 0 {
		return errors.New("短信内容不能为空")
	}
	if argv.Typeid == 0 {
		return errors.New("短信类型必须是1或2")
	}
	if argv.Typeid == 1 && len(argv.VerifCode) == 0 {
		return errors.New("验证短信请填写验证码")
	}
	v := url.Values{}
	v.Add("name", s.User)
	v.Add("pwd", s.Pwd)
	v.Add("content", argv.Content)
	v.Add("mobile", argv.Mobile)
	v.Add("stime", argv.SendTiime)
	v.Add("sign", s.Signature)
	v.Add("type", "pt")
	v.Add("extno", "")
	http_query := v.Encode()
	//http_query := fmt.Sprintf("name=%s&pwd=%s&content=%s&mobile=%s&stime=%s&sign=%s&type=pt&extno=", s.User, s.Pwd, argv.Content, argv.Mobile, argv.SendTiime, s.Signature)
	err := s.Get(http_query)

	//写入短信发送日志
	log := models.SmsSendLog{}
	log.DepartmentId = argv.DepartmentId
	log.CreatedBy = argv.CreatedBy
	log.VerifCode = argv.VerifCode
	log.Content = argv.Content
	log.Typeid = argv.Typeid
	log.Mobile = argv.Mobile
	if err == nil { //发送成功，开始写日志
		log.Status = 1
	} else {
		log.Status = 0 //发送失败
	}
	if err := log.SmsInsert(); err != nil {
		utils.LogWarning(err) //记录错误情况
	}

	return err
}

//发送验证码
func (s *SmsService) SendVerifCode(argv *SmsArgv) error {
	if !utils.CheckMobile(argv.Mobile) {
		return errors.New("手机号不正确")
	}
	//完成短信验证码及短信内容
	verifCode := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
	argv.VerifCode = verifCode
	argv.Content = verifCode + "(动态验证码)，请在30分钟内填写"
	argv.Typeid = 1 //验证类型短信
	//判断手机号发送频次日超3次将拒绝继续发送
	if count := models.SendSmsCount(argv.Mobile); count >= 3 {
		return errors.New("验证短信超出当日上限3条")
	}
	return s.Send(argv)
}

//批量发送
func (s *SmsService) BatchSend(argv *SmsArgv) error {

	if len(argv.Mobiles) <= 0 {
		return errors.New("手机号不能为空")
	}

	if len(argv.Content) <= 0 {
		return errors.New("短信内容不能为空")
	}
	var (
		mobile string
		key    string
	)
	//组合字串，非正常手机号剔除
	key = ""
	for k, _ := range argv.Mobiles {
		if utils.CheckMobile(argv.Mobiles[k]) {
			mobile = mobile + key + argv.Mobiles[k]
			key = ","
		}
	}
	v := url.Values{}
	v.Add("name", s.User)
	v.Add("pwd", s.Pwd)
	v.Add("content", argv.Content)
	v.Add("mobile", argv.Mobile)
	v.Add("stime", argv.SendTiime)
	v.Add("sign", s.Signature)
	v.Add("type", "pt")
	v.Add("extno", "")
	http_query := v.Encode()

	//http_query := fmt.Sprintf("name=%s&pwd=%s&content=%s&mobile=%s&stime=%s&sign=%s&type=pt&extno=", s.User, s.Pwd, argv.Content, mobile, argv.SendTiime, s.Signature)
	return s.Get(http_query)
}

//接口访问[Get访问]
func (s *SmsService) Get(http_query string) error {
	uri := fmt.Sprintf(getSmsApiURL, http_query)
	resp, err := http.Get(uri)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, resp.StatusCode)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	return s.checkSendStatus(string(body))
}

//验证短信发送状态
func (s *SmsService) checkSendStatus(value string) error {
	if len(value) <= 0 {
		return errors.New("短信返回数据错误")
	}
	//拆分返回字串
	split := strings.Split(value, ",")

	var statusInfo string

	status, err := strconv.Atoi(split[0])
	if err != nil {
		return err
	}

	switch status {
	case 0:
		statusInfo = ""
	case 1:
		statusInfo = "含有敏感词汇"
	case 2:
		statusInfo = "余额不足"
	case 3:
		statusInfo = "没有号码"
	case 4:
		statusInfo = "包含sql语句"
	case 10:
		statusInfo = "账号不存在"
	case 11:
		statusInfo = "账号注销"
	case 12:
		statusInfo = "账号停用"
	case 13:
		statusInfo = "IP鉴权失败"
	case 14:
		statusInfo = "格式错误"
	case -1:
		statusInfo = "系统异常"
	default:
		statusInfo = "未知错误"
	}
	if len(statusInfo) > 0 {
		return errors.New("接口：" + statusInfo)
	}

	return nil
}
